#include "Glas.h"

double Glas::bodenFunc(const double x, const bool abl, const double height){
	if(abl){
		return 2.7602 - 2*(x*x);
	}else{
		return (-.0014*(x*x)*3) + (2*0.0489*(x)) - (.3478);
	}
}

double Glas::glasFunc(const double x, const bool abl, const double height){
		//funktion aus Fachareit entliehen / Weizenbierglas
	if(abl){
		return (-.0014*(x*x*x)) + (0.0489*(x*x)) - (.3478*x) + 2.7602;
	}else{
		return (-.0014*(x*x)*3) + (2*0.0489*(x)) - (.3478);
	}
}

Geometry* Glas::createRot(const int lsteps, const int wsteps,
		const double height, double (*pfunc)(double x, bool abl, double height)){

	//Variablen f�r das Glas (f�r eine Umdrehung und das Intervall f�r die Funktion
	const double umdrehung	= 2*PI;
	const double interval	= height*PI;

	//Initialisierung der Pointer
	ref_ptr<Geometry> geom = new Geometry;
	ref_ptr<Vec3Array> vertices = new Vec3Array();
	ref_ptr<Vec3Array> normals = new Vec3Array();
	ref_ptr<DrawElementsUInt> indices = new DrawElementsUInt(GL_TRIANGLE_STRIP);

	//Die Feinheit der Kurve anpassen
	double xstep = umdrehung / lsteps;
	double ystep = interval / wsteps;

	// Vertics und Normalen setzten
	// Erteschliefe f�r den y weg 2 f�r die Rotation
	for (double  y = 0.0; y<=interval; y += ystep){
		for (double x= 0.0; x<= umdrehung; x+=xstep ){
			/*F�r Kegel Zylinder Schachfiguren S�ulen*/
			vertices->push_back(Vec3d(pfunc(y,true,1)*cos(x),pfunc(y,true,1)*sin(x),y));
			Vec3d normal (pfunc(y,false,1)*cos(x),pfunc(y,false,1)*sin(x),1);

			normal.normalize();
			normals->push_back(normal);
		}
	}


	//Indicessetzten
	for (int i=0; i <lsteps; i+=2){
		for (int j=0; j<=wsteps; j++){
			indices->push_back( i*(wsteps+1)+j );
			indices->push_back( (i+1)*(wsteps+1)+j );
		}
		if ((i+2)*(wsteps+1)+wsteps < (lsteps+1)*(wsteps+1) ){
			for (int j=wsteps; j>=0; j--){
				indices->push_back( (i+2)*(wsteps+1)+j );
				indices->push_back( (i+1)*(wsteps+1)+j );
			}
		}
	}

	//Farbe Blau light
	osg::ref_ptr<osg::Vec4Array> colors = new osg::Vec4Array;
    colors->push_back( osg::Vec4(0.6f, 1.0f, 1.0f, 0.5f) );

	//Alle Array and das Geometry Objekt �bergeben
	geom->setVertexArray (vertices.get());
	geom->addPrimitiveSet(indices.get());
	geom->setNormalArray(normals.get());
	geom->setNormalBinding(Geometry::BIND_PER_VERTEX);
	geom->setColorArray(colors.get());
	geom->setColorBinding( osg::Geometry::BIND_OVERALL );


	return geom.release();
}


ref_ptr<Geode> Glas::get(){
	// baue Geometry
	ref_ptr<Geometry> corpus = createRot(30,30,6.5,glasFunc);
	ref_ptr<Geometry> boden = createRot(30,30,0.375,bodenFunc);

	// baue Gemetrie-Knoten
    ref_ptr<Geode> model = new Geode;
    model->addDrawable(corpus.get());
	model->addDrawable(boden.get());



	//transparenz setzten
	// aktuelles Stateset w�hlen und linken / Transperenz setzten
	osg::StateSet* stateset = model->getOrCreateStateSet();
	stateset->setRenderingHint( osg::StateSet::TRANSPARENT_BIN );
    
    //Alphablending setzten
	osg::ref_ptr<osg::BlendFunc> blendFunc = new osg::BlendFunc;
	blendFunc->setFunction( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
	stateset->setAttributeAndModes( blendFunc );

	return model;
}

Glas::Glas(){}

Glas::~Glas(){}
